<?php

declare (strict_types = 1);

namespace app\common\service;

use app\common\exception\AdminException;
use app\common\repository\BaseRepository;
use think\facade\Request;
use think\facade\Db;
use think\facade\Log;

abstract class BaseService
{
    protected $repository;

    public function __construct(BaseRepository $repository)
    {
        $this->repository = $repository;
    }

    /**
     * 获取分页参数
     *
     * @param int $defaultPageSize 默认每页显示的数量
     * @return array
     */
    protected function getPaginationParams(int $defaultPageSize = 15): array
    {
        $page = Request::param('page', 1, 'intval');
        $pageSize = Request::param('page_size', $defaultPageSize, 'intval');

        return [
            max($page, 1), // 确保页码不小于1
            max($pageSize, 1), // 确保每页数量不小于1
        ];
    }

    /**
     * 强制启用事务的执行
     *
     * @param callable $closure 必须返回业务结果的操作
     * @param string $connection 指定数据库连接
     */
    public function transaction(
        callable $closure,
        string $connection = 'mysql'
    ): mixed {
        Db::connect($connection)->startTrans();
        try {
            $result = $closure();
            Db::commit();
            return $result;
        } catch (\Throwable $e) {
            Db::rollback();
            $this->logTransactionFailure($e, $connection);
            throw new AdminException($e->getMessage()); // 或抛出自定义异常
        }
    }

    /**
     * 专用日志方法
     *
     * @param \Throwable $e
     * @param string $connection
     * @return void
     */
    protected function logTransactionFailure(\Throwable $e, string $connection): void
    {
        Log::error("事务操作失败 [{$connection}]", [
            'error' => $e->getMessage(),
            'sql'   => Db::getLastSql(),
            'trace' => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5)
        ]);
    }

    /**
     * @param $name
     * @param $arguments
     * @return mixed
     */
    public function __call($name, $arguments)
    {
        return call_user_func_array([$this->repository, $name], $arguments);
    }
}